package com.jinhe.tss.cms;

import java.io.File;
import java.util.List;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit38.AbstractTransactionalJUnit38SpringContextTests;
import org.springframework.test.context.transaction.TransactionConfiguration;

import com.jinhe.tss.cms.dao.IArticleDao;
import com.jinhe.tss.cms.dao.IChannelDao;
import com.jinhe.tss.cms.entity.ArticleType;
import com.jinhe.tss.cms.service.IArticleService;
import com.jinhe.tss.cms.service.IArticleTypeService;
import com.jinhe.tss.cms.service.IChannelService;
import com.jinhe.tss.component.dynproperty.support.IRemotePropertyService;
import com.jinhe.tss.component.log.maintain.LogService;
import com.jinhe.tss.component.support.test.IH2DBServer;
import com.jinhe.tss.component.support.test.TestUtil;
import com.jinhe.tss.core.Global;
import com.jinhe.tss.core.sso.IdentityCard;
import com.jinhe.tss.core.sso.TokenUtil;
import com.jinhe.tss.core.sso.context.Context;
import com.jinhe.tss.core.util.FileHelper;
import com.jinhe.tss.core.util.URLUtil;
import com.jinhe.tss.core.util.XMLDocUtil;
import com.jinhe.tss.um.UMConstants;
import com.jinhe.tss.um.helper.dto.OperatorDTO;
import com.jinhe.tss.um.permission.PermissionHelper;
import com.jinhe.tss.um.permission.PermissionService;
import com.jinhe.tss.um.service.ILoginService;
import com.jinhe.tss.um.service.IResourceRegisterService;

/**
 * Junit Test 类里执行构造函数的时候无事务，即构造函数不在单元测试方法的事物边界内。
 */
@ContextConfiguration(
        locations={
                "classpath:spring/testCMSApplicationContext.xml",  
                "classpath:spring/component-applicationContext.xml",  
                "classpath:spring/core-applicationContext.xml",
                "classpath:spring/um-applicationContext.xml",
                "classpath:spring/cms-applicationContext.xml",
                "classpath:spring/cms-upload-applicationContext.xml"
              } 
              , inheritLocations = false // 是否要继承父测试用例类中的 Spring 配置文件，默认为 true
      )
@TransactionConfiguration(defaultRollback = false) // 不自动回滚，否则后续的test中没有初始化的数据
public abstract class TxSupportTest4CMS extends AbstractTransactionalJUnit38SpringContextTests { 
 
    protected Logger log = Logger.getLogger(this.getClass());    
    
    @Autowired protected IResourceRegisterService resourceRegisterService;
    @Autowired protected IRemotePropertyService propertyService;
    @Autowired protected ILoginService loginSerivce;
    @Autowired protected PermissionService permissionService;
    @Autowired protected PermissionHelper permissionHelper;
    @Autowired protected LogService logService;
    
    @Autowired protected IH2DBServer dbserver;
	
    @Autowired protected IArticleTypeService articleTypeService;
    @Autowired protected IChannelService channelService;
    @Autowired protected IArticleService articleService;
    @Autowired protected IChannelDao channelDao;
    @Autowired protected IArticleDao articleDao;
    
    protected void setUp() throws Exception {
        super.setUp();
        Global.setContext(super.applicationContext);
        Context.setResponse(new MockHttpServletResponse());
        
        // DB数据在一轮跑多个单元测试中初始化一次就够了。
        if( dbserver.isPrepareed() ) {
            return;
        }
        
        init();
        
        dbserver.setPrepareed(true);
    }
 
    /**
     * 初始化CMS的动态属性相关模板
     */
    protected void init() {
    	// 初始化数据库脚本
    	String sqlpath = TestUtil.getInitSQLDir();
    	log.info( " sql path : " + sqlpath);
        TestUtil.excuteSQL(sqlpath + "/component");
        TestUtil.excuteSQL(sqlpath + "/um");
    	TestUtil.excuteSQL(sqlpath + "/cms");
    	
    	// 初始化虚拟登录用户信息
        login(UMConstants.ADMIN_USER_ID, UMConstants.ADMIN_USER_NAME);
        
        /* 初始化应用系统、资源、权限项 */
        Document doc = XMLDocUtil.createDocByAbsolutePath(sqlpath + "/cms-application-config.xml");
        resourceRegisterService.setInitial(true);
        resourceRegisterService.applicationRegisterByXML(doc, UMConstants.PLATFORM_SYSTEM_APP);
        resourceRegisterService.setInitial(false);
        
        /** 注册动态属性实体（包括站点栏目、文章等） */
        File path = new File(URLUtil.getResourceFileUrl(TestUtil.DYN_ENTITY_CONFIG_PATH).getFile());
        List<String> files = FileHelper.listFilesByType(".xml", path);
        for( String fileName : files ){
            if (!"ArticleProperties.xml".equals(fileName)) {
                Document tempDoc = XMLDocUtil.createDoc(TestUtil.DYN_ENTITY_CONFIG_PATH + "/" + fileName);
                propertyService.importDynableEntity(tempDoc.asXML());
            }
        }
        
        /** 初始化一个普通文章类型 */
        initCommonArticleType();
    }
 
    protected static ArticleType defaultArticleType;
    
    /** 初始化一个普通文章类型 */
    private void initCommonArticleType() {
        ArticleType articleTypeGroup = new ArticleType();
        articleTypeGroup.setName("基本类型组");
        articleTypeGroup.setParentId(CMSConstants.HEAD_NODE_ID);
        articleTypeGroup.setIsGroup(CMSConstants.TRUE);
        articleTypeGroup = articleTypeService.createArticleType(articleTypeGroup);
        
        defaultArticleType = new ArticleType();
        defaultArticleType.setName("默认文章类型");
        defaultArticleType.setParentId(articleTypeGroup.getId());
        defaultArticleType.setIsGroup(CMSConstants.FALSE);
        defaultArticleType = articleTypeService.createArticleType(defaultArticleType);
        
        // 将文章的模板导入到动态属性实体中
        Document doc = XMLDocUtil.createDoc(CMSConstants.TEMPLATE_ARTICLE_PROPERTY);
        Element root = doc.getRootElement();
        root.addAttribute("name", defaultArticleType.getName());
        root.addAttribute("code", defaultArticleType.getEntityCode());
        propertyService.importDynableEntity(doc.asXML());
    }
    
    protected void login(Long userId, String loginName) {
    	OperatorDTO loginUser = new OperatorDTO(userId, loginName);
    	String token = TokenUtil.createToken("1234567890", userId); 
        IdentityCard card = new IdentityCard(token, loginUser);
        Context.initIdentityInfo(card);
        
        // 获取登陆用户的权限（拥有的角色）并保存到用户权限（拥有的角色）对应表
        List<Object[]> userRoles = loginSerivce.getUserRolesAfterLogin(userId);
        permissionService.saveUserRolesAfterLogin(userRoles, userId);
    }
}
